package com.edu.hit.showdemo;

import cn.edu.hit.core.Document;
import cn.edu.hit.core.Pair;
import cn.edu.hit.core.combine.CombineLoader;
import cn.edu.hit.core.db.*;
import cn.edu.hit.core.message.MessageLoader;
import cn.edu.hit.kg.data.GraphData;
import cn.edu.hit.kg.entity.Component;
import cn.edu.hit.kg.entity.Fault;
import cn.edu.hit.kg.entity.Signal;
import org.apache.commons.collections.ListUtils;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static cn.edu.hit.core.Adapter.VALUE;
import static cn.edu.hit.core.combine.CombineAdapter.*;
import static cn.edu.hit.core.message.MessageAdapter.*;
import static cn.edu.hit.core.message.MessageAdapter.ID;

public class App {
    public static void main(String[] args) {

        DataConnection connection = DataConnectionLoader.getInstance();
        DataReader dataReader = connection.getReader();
        DBReadHelper dbHelper = new DBReadHelper(dataReader);

        MessageLoader messageLoader = MessageLoader.getInstance();

        CombineLoader combineLoader = CombineLoader.getInstance();

        //在mongo.data读取出的文件中，根据规则type=generator得到配置文件中的所有机组号
        Set<Document> unitSet = dataReader.queryByTemplate((Filters.eq("type", "generator"))).stream()
                .collect(Collectors.toSet());

        long timestamp = System.currentTimeMillis();
        for (Document workUnit : unitSet) {
            try {
                String unitId = workUnit.getString("MachineNo");
                String unit_id = workUnit.getObjectId("_id");
                List<Document> documentStream = dbHelper.loadConfigure(unit_id, "signal");

                List<Map> signals = messageLoader.transfer(documentStream.stream().map(d -> (Map) d),
                        d -> d.get(ID).toString(), d -> d.get(DATA_SOURCE).toString(), timestamp)
                        .collect(Collectors.toList());

                System.out.println(signals);


                ((List<Document>) dataReader.queryByTemplate(
                        Filters.and(
                                Filters.eq("name", unit_id),
                                Filters.eq("type", "package"))))
                        .stream()
                        .sorted(Comparator.comparing(x -> ((Document) x).getInteger("processStep")).reversed())
                        .map(doc -> doc.getObjectId("_id"))
                        .forEach(chain -> {
                            List<Document> featureConfigStream = dbHelper.loadConfigure(chain, "feature");

                            Map<String, Object> rawFeatures = signals.stream().collect(Collectors.groupingBy(
                                    document -> document.get(PORT_ID).toString(),
                                    Collectors.collectingAndThen(Collectors.toSet(), set -> set.stream().findFirst().get())
                            ));

                            //根据配置的数据源去获取数据
                            List<Map> results = combineLoader.transfer(featureConfigStream.stream().map(d -> (Map) d),
                                    d -> d.get(ID).toString(), d -> d.get(COMBINE_STRATEGY).toString(), Pair.of(timestamp, rawFeatures)).collect(Collectors.toList());
                            signals.addAll(results);
                        });
                //将测点数据转化成特征值

                System.out.println(signals);
                List<Signal> rawFeatures = getKnowledgeSignals(signals);
                System.out.println(rawFeatures);

                GraphData graphData = GraphData.getInstance();

                graphData.getIdSetByLabel("Fault").stream().map(Fault::loadById)
                        .peek(fault -> fault.matchSignal(rawFeatures,timestamp,unitId))
                        .filter(fault -> fault.isMatched())
                        .collect(Collectors.groupingBy(f -> f.isFinished(unitId)));

            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }

    }

    public static List<Signal> getKnowledgeSignals(List<Map> signals) {
        List<Signal> rawFeatures = signals.stream()
                .filter(signal -> signal.containsKey("signalType"))
                .map(document -> {
                    Signal signal = new Signal();
                    signal.setFeatureType(document.get(FEATURE_TYPE).toString());
                    signal.setValue(document.get(VALUE));
                    Map component = Component.getByName(document.get(COMPONENT_NAME).toString());
                    signal.setComponent(component);
                    signal.setSource(document);
                    return signal;
                })
                .collect(Collectors.toList());

        List<Signal> rawSignals = signals.stream()
                .filter(signal -> !signal.containsKey("signalType"))
                .map(document -> {
                    Signal signal = new Signal();
                    signal.setFeatureType(document.get("portName").toString());
                    signal.setValue(document.get(VALUE));
                    signal.setComponent(null);
                    signal.setSource(document);
                    return signal;
                }).collect(Collectors.toList());

        return ListUtils.union(rawFeatures, rawSignals);
    }
}
